home *** CD-ROM | disk | FTP | other *** search
- UNIT U_EGD_0a; {Last mod by JFH on 07/20/95}
-
- { DEFINES EXAMPLE READER AND ACCESS CLASSES FOR AutoCADD DXF FILES }
-
- { Pgm. 07/20/95 by John F Herbster for CIS Delphi Object Pascal Lib. }
-
- {=====} INTERFACE {====================================================}
-
- {-----} USES {-----}
- U_EGB_0a,
- SysUtils;
-
- {----- The File Image of Binary DXF data ------------------------------}
-
- CONST {For defining the binary record structure.}
- dtUnk = 0; dtInt = 1; dtLong = 2; dtDbl = 3; dtZStr = 4;
- dtExt = 5{Marker for extended code};
- deInt = 6; deLong = 7; deDbl = 8; deZStr = 9;
- deSBB = 10 {Small Binary Blocks};
- deByte = 11;
-
- { The following record is the image of the datum as used in the binary
- version of the DXF files. This image may be tracked along in the
- binary buffers and/or pulled out and packed together in byte arrays.}
-
- TYPE
- zString = array [1..256] of char;
- pDxfBinaryDatum = ^tDxfBinaryDatum;
- tDxfBinaryDatum = record {This is the varient record itself.}
- Case SCode: byte of {Array DxfGFmt translates SCode into "dt" #s.}
- dtInt: (bInt: integer{for integers});
- dtLong: (bLong: longint{for codes 90..99});
- dtDbl: (bDbl: double {for floating point});
- dtZStr: (bZStr: zString{for character data});
- dtExt: (Case ECode: integer of {DxfXFmt cvts GExt into "de" #s.}
- deInt: (cInt: integer{for integers});
- deLong: (cLong: longint{for 32-bit ints});
- deDbl: (cDbl: double {for floating point});
- deZStr: (cZStr: zString{for character data});
- deSBB: (cStr: string {for small binary objects});
- deByte: (cByte: byte));
- end;
-
- {----- Functions for creating the binary records -----}
-
- Procedure MkBDxfIntRec
- (const Code: integer; const Value: longint;
- var Rec: tDxfBinaryDatum; var Lgh: word);
-
- Procedure MkBDxfDblRec
- (const Code: integer; const Value: extended;
- var Rec: tDxfBinaryDatum; var Lgh: word);
-
- Procedure MkBDxfStrRec
- (Const Code: integer; const Value: string;
- var Rec: tDxfBinaryDatum; var Lgh: word);
-
- {----- Functions for interpreting binary DXF records -----}
-
- Procedure GetCodeAndLgh
- (pRec: pDxfBinaryDatum; var Code: integer; var Lgh: word);
-
- {----- tBinaryDxfScanner Class object -----}
-
- TYPE
- tBinaryDxfScanner = class (tBufferedFileScanner)
- Constructor Create
- (const Pathname: string; aClusterSize: word);
- { opens the file. }
- Function LocNextDxfRec
- (var pRec: pDxfBinaryDatum; var GroupCode: integer): boolean;
- end;
-
- TYPE
- tBufferedFileWriter = class
- Constructor Create
- (const Pathname: string; aClusterSize: word);
- { creates a new file and opens it, overwriting any previous. }
- Procedure WriteRec (var Rec; NbrBytes: word);
- { writes the NbrBytes starting at Rec to the buffer. When the
- buffer is full it is copied to disk. }
- Destructor Distroy;
- { copies the stuff, if any, in the buffer out to the file,
- closes the file, and returns the buffer memory to system. }
- protected
- Chan: file;
- pBuf: pByteArray;
- SizeOfBuf: word;
- oi: word; {index of next available spot in buffer.}
- Procedure FlushToDisk;
- end;
-
-
- {=====} implementation {===============================================}
-
- Function zStrLgh (const zs: zString): word;
- Var i: word;
- Begin
- i:=0; While (i<255) and (zs[i+1]<>#0) do inc(i);
- Result:=i;
- End;
-
- { Array DxfGFmt(g) will convert the 0..255 group code into a case code
- designating the kind of storage.}
- CONST
- DxfGFmt: array [byte] of byte =
- {000}(4,4,4,4,4, 4,4,4,4,4, 3,3,3,3,3, 3,3,3,3,3, {4=zStr}
- {020} 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, {3=Dbl}
- {040} 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3, 3,3,3,3,3,
- {060} 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, 1,1,1,1,1, {1=Int}
- {080} 0,0,0,0,0, 0,0,0,0,0, 2,2,2,2,2, 2,2,2,2,2, {2=Long}
- {100} 4,0,4,0,0, 4,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, {0=Unk}
- {120} 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
- {140} 3,3,3,3,3, 3,3,3,0,0, 0,0,0,0,0, 0,0,0,0,0,
- {160} 0,0,0,0,0, 0,0,0,0,0, 1,1,1,1,1, 1,0,0,0,0,
- {180} 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0,
- {200} 0,0,0,0,0, 0,0,0,0,0, 3,0,0,0,0, 0,0,0,0,0,
- {220} 3,0,0,0,0, 0,0,0,0,0, 3,0,0,0,0, 0,0,0,0,0,
- {240} 0,0,0,0,0, 0,0,0,0,0, 0,0,0,0,0, dtExt);
- NbrXFmt = 9; {Number of extended ranges}
- DxfXFmt: array [0..NbrXFmt-1] of record R1,R2: integer; DE: word end =
- { This array defines the extra ranges (R1..R2) of data types.}
- ((R1: 280;R2: 289;DE:deByte), {Byte value}
- (R1: 300;R2: 309;DE:deZStr), {Arb. text}
- (R1: 310;R2: 319;DE:deZStr), {Hex handle}
- (R1: 320;R2: 369;DE:deZStr), {Hex handle}
- (R1: 999;R2: 999;DE:deZStr), {Comment}
- (R1:1000;R2:1009;DE:deDbl),
- (R1:1010;R2:1059;DE:deDbl),
- (R1:1060;R2:1069;DE:deInt),
- (R1:1071;R2:1071;DE:deLong));
-
- Procedure GetCodeAndLgh
- (pRec: pDxfBinaryDatum; var Code: integer; var Lgh: word);
- Var i: integer;
- Begin
- If pRec=nil then begin Code:=-$800; Lgh:=0; EXIT end;
- With pRec^ do begin
- Code:=SCode;
- Case DxfGFmt[Code] of
- dtInt: Lgh:=SizeOf(integer)+1;
- dtLong: Lgh:=SizeOf(longint)+1; {R13DXF.HLP didn't incl.}
- dtDbl: Lgh:=SizeOf(double)+1{BCode};
- dtZStr: Lgh:=zStrLgh(bZStr)+1{BCose}+1{term};
- dtExt: begin
- i:=0; Code:=ECode;
- While i<NbrXFmt do with DxfXFmt[i] do begin
- If (R1<=Code) and (Code<=R2)
- then begin
- Case DE {the data storage code} of
- deInt: Lgh:=SizeOf(integer)+3;
- deLong: Lgh:=SizeOf(longint)+3;
- deDbl: Lgh:=SizeOf(double)+3;
- deZStr: Lgh:=zStrLgh(cZStr)+1+4;
- deSBB: Lgh:=length(cStr)+1+4; {Small Binary Blocks}
- deByte: Lgh:=1+2+1;
- else Lgh:=0;
- end;
- i:=MaxInt;
- end
- else inc(i);
- end{While};
- If i=NbrXFmt then Lgh:=0;
- end{case};
- else {Unknown} Lgh:=0;
- end;
- end;
- End;
-
- {----- Functions for creating the binary records -----}
-
- Procedure MkBDxfIntRec
- (const Code: integer; const Value: longint;
- var Rec: tDxfBinaryDatum; var Lgh: word);
- Var stype: word; s: string; b: byte; i: integer;
- Begin With Rec do Begin
- FillChar(Rec,SizeOf(Rec),0); {Just for debugging!!}
- If (Code>=0) and (Code<=255)
- then {short} begin
- SCode:=Code;
- Case DxfGFmt[Code] of
- dtInt: begin bInt :=Value; Lgh:=SizeOf(bInt)+1; end;
- dtLong: begin bLong:=Value; Lgh:=SizeOf(bLong)+1 end;
- dtDbl: begin bDbl :=Value; Lgh:=SizeOf(bDbl)+1 end;
- dtZStr: begin
- Str(Value:0,s);
- For b:=1 to length(s) do bzStr[b]:=s[b];
- bzStr[length(s)+1]:=#0;
- Lgh:=length(s)+1+1 end;
- else begin Lgh:=0 end;
- end{cases};
- end{short}
- else {extended} begin
- SCode:=255; ECode:=Code; i:=0;
- While i<NbrXFmt do with DxfXFmt[i] do begin
- If (R1<=Code) and (Code<=R2)
- then begin
- Case DE {the data storage code} of
- deInt: begin cInt :=Value; Lgh:=SizeOf(cInt)+3 end;
- deLong: begin cLong:=Value; Lgh:=SizeOf(cLong)+3 end;
- deDbl: begin cDbl :=Value; Lgh:=SizeOf(double)+3 end;
- deByte: begin cByte:=Value; Lgh:=1+2+1 end;
- else Lgh:=0;
- end;
- i:=MaxInt;
- end{did it}
- else inc(i);
- end{While};
- end{extended};
- End{With}; End;
-
- Procedure MkBDxfDblRec
- (const Code: integer; const Value: extended;
- var Rec: tDxfBinaryDatum; var Lgh: word);
- Begin
- Lgh:=0; {Define the real thing later.}
- End;
-
- Procedure MkBDxfStrRec
- (Const Code: integer; const Value: string;
- var Rec: tDxfBinaryDatum; var Lgh: word);
- Var b: byte; i,ec: integer; li: longint; d: double;
- Begin With Rec do Begin
- FillChar(Rec,SizeOf(Rec),0); {Just for debugging!!}
- If (Code>=0) and (Code<=255)
- then {short} begin
- SCode:=Code;
- Case DxfGFmt[Code] of
- dtInt: begin
- Val(Value,li,ec);
- If (ec=0) and (li>=-$8000) and (li<$8000)
- then begin bInt:=li; Lgh:=SizeOf(bInt)+1 end
- else Lgh:=0;
- end;
- dtLong: begin
- Val(Value,li,ec);
- If (ec=0)
- then begin bLong:=li; Lgh:=SizeOf(bLong)+1 end
- else Lgh:=0;
- end;
- dtDbl: begin
- Val(Value,d,ec);
- If (ec=0)
- then begin bDbl:=d; Lgh:=SizeOf(bDbl)+1 end
- else Lgh:=0;
- end;
- dtZStr: begin
- For b:=1 to length(Value) do bzStr[b]:=Value[b];
- bzStr[length(Value)+1]:=#0;
- Lgh:=length(Value)+1+1 end;
- else begin Lgh:=0 end;
- end{cases};
- end{short}
- else {extended} begin
- SCode:=255; ECode:=Code; i:=0;
- While i<NbrXFmt do with DxfXFmt[i] do begin
- If (R1<=Code) and (Code<=R2)
- then begin
- Case DE {the data storage code} of
- deInt: begin
- Val(Value,li,ec);
- If (ec=0) and (li>=-$8000) and (li<$8000)
- then begin cInt:=li; Lgh:=SizeOf(cInt)+3 end
- else Lgh:=0;
- end;
- deLong: begin
- Val(Value,li,ec);
- If (ec=0)
- then begin cLong:=li; Lgh:=SizeOf(cLong)+3 end
- else Lgh:=0;
- end;
- deDbl: begin
- Val(Value,d,ec);
- If (ec=0)
- then begin bDbl:=d; Lgh:=SizeOf(bDbl)+3 end
- else Lgh:=0;
- end;
- deByte: begin
- Val(Value,li,ec);
- If (ec=0) and (li>=0) and (li<256)
- then begin cByte:=li; Lgh:=SizeOf(cByte)+3 end
- else Lgh:=0;
- end;
- deZStr: begin
- For b:=1 to length(Value) do czStr[b]:=Value[b];
- czStr[length(Value)+1]:=#0;
- Lgh:=length(Value)+1+1+2;
- end;
- else Lgh:=0;
- end{cases};
- i:=MaxInt;
- end{did it}
- else inc(i);
- end{While};
- end{extended};
- End{With}; End;
-
- {----- tBinaryDxfScanner Class object -----}
-
- Constructor tBinaryDxfScanner.Create
- (const Pathname: string; aClusterSize: word);
- Begin
- Inherited Create(Pathname,aClusterSize,SizeOf(tDxfBinaryDatum));
- { Note that the SizeOf will give the maximum size of the record.}
- End;
-
- Function tBinaryDxfScanner.LocNextDxfRec
- (var pRec: pDxfBinaryDatum; var GroupCode: integer): boolean;
- Var NbrFound,LghRec: word;
- Begin
- If LocNextVarLghRec(pByteArray(pRec),NbrFound)
- then begin
- GetCodeAndLgh(pRec,GroupCode,LghRec);
- If LghRec=0 then Result:=false
- Else begin CurIndex:=PrevIndex+LghRec; Result:=true end;
- end
- else Result:=false;
- End;
-
- Constructor tBufferedFileWriter.Create
- (const Pathname: string; aClusterSize: word);
- { creates a new file and opens it, overwriting any previous. }
- Begin
- Inherited Create;
- Assign(Chan,Pathname); ReWrite(Chan,1{record size});
- SizeOfBuf:=aClusterSize;
- GetMem(PBuf,SizeOfBuf);
- End;
-
- Procedure tBufferedFileWriter.WriteRec (var Rec; NbrBytes: word);
- { writes the NbrBytes starting at Rec to the buffer. When the
- buffer is full it is copied to disk. }
- Var i: word;
- Begin
- For i:=1 to NbrBytes do begin
- pBuf^[oi]:=tByteArray(Rec)[i];
- Inc(oi);
- If oi=SizeOfBuf then FlushToDisk;
- end;
- End;
-
- Procedure tBufferedFileWriter.FlushToDisk;
- Begin
- If oi>0
- then BlockWrite(Chan,pBuf^,oi);
- oi:=0;
- End;
-
- Destructor tBufferedFileWriter.Distroy;
- { copies the stuff, if any, in the buffer out to the file,
- closes the file, and returns the buffer memory to system. }
- Begin
- If oi>0
- then FlushToDisk;
- Close(Chan);
- If SizeOfBuf>0 then FreeMem(pBuf,SizeOfBuf);
- End;
-
- {=====} END. {=========================================================}
-
-